package com.buli.blmall.admin.core.interceptor;

import com.buli.blmall.admin.common.domain.SysLoginUser;
import com.buli.blmall.admin.consts.CacheKey;
import com.buli.blmall.admin.consts.Constants;
import com.buli.blmall.admin.core.annotion.IgnorePerm;
import com.buli.blmall.admin.core.horder.LoginUserHolder;
import com.buli.blmall.admin.exception.LoginException;
import com.buli.blmall.admin.exception.PermissionException;
import com.buli.blmall.admin.exception.error.LoginErrorCode;
import com.buli.blmall.admin.utils.PathMatchUtil;
import com.buli.blmall.admin.utils.ServletUtil;
import com.buli.blmall.admin.core.cache.RedisClient;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * @author xiang.gao
 * @date 2024/12/24 18:11
 */
@Slf4j
@Component
@AllArgsConstructor
public class SecurityInterceptor implements HandlerInterceptor {

    private final RedisClient redisClient;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String authToken = request.getHeader(Constants.AUTHORIZATION_KEY);
        //未登录
        if (authToken == null) {
            throw new LoginException(LoginErrorCode.UNLOGING_ERROR);
        }
        SysLoginUser loginUser = redisClient.getValue(CacheKey.SYSTEM_LOGIN_TOKEN.concat(authToken));
        if (loginUser == null) {
            log.debug("token已失效,请重新登录!");
            throw new LoginException(LoginErrorCode.UNLOGING_ERROR);
        }
        //权限不足
        if (permissionDenied(request, handler, loginUser)) {
            log.debug("权限不足,请求路径:{}", request.getRequestURI());
            throw new PermissionException();
        }
        // 用户已登录，继续处理请求
        LoginUserHolder.set(loginUser);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        LoginUserHolder.remove();
    }

    /**
     * 访问权限
     * @param request
     * @param handler
     * @param loginUser
     * @return
     */
    private boolean permissionDenied(HttpServletRequest request, Object handler, SysLoginUser loginUser) {
        if (request.getMethod().equals(ServletUtil.METHOD_OPTIONS)) {
            return false;
        }
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            IgnorePerm ingnorePerm  = handlerMethod.getMethodAnnotation(IgnorePerm.class);
            if (ingnorePerm != null) {
                return false;
            }
        }
        return loginUser.getPermission().stream().noneMatch(s -> PathMatchUtil.match(s, request.getRequestURI()));
    }

}
